In [ ]:
#import all the libraries needed
from imports import *
# import my functions
from function_store import *

# Define the path to the directories containing the VNA data
directory_1 = ('/Users/horatiocox/Desktop/VNA_Analysis/mag_angle_260424/')

directory_3 = ('/Users/horatiocox/Desktop/VNA_Analysis/CPW_mem_oscillator_220524/Oscillator/')

# Import the data from the VNA files
s2p_files_1 = import_data(directory_1)

s2p_files_3 = import_data(directory_3)
# Remove duplicate frequency points from all the thru data to prevent errors with skrf functions
s2p_files_1 = duplicate_check(s2p_files_1)

s2p_files_3 = duplicate_check(s2p_files_3)
1 run1_r0c0_thru Wafer0_r0_c0_ISS_thru_LRM+_1.S2P
2 run2_rNonecNone_thru ISS_thru_LRRM_1.S2P
3 run3_r10c1_thru Wafer2_r10_c1_thru_1.S2P
4 run4_r10c13_thrunotaper Wafer2_r10_c13_thrunotaper_1.S2P
5 run5_r10c5_open Wafer2_r10_c5_open_1.S2P
6 run6_r10c9_opensig Wafer2_r10_c9_opensig_1.S2P
7 run7_r10c11_short Wafer2_r10_c11_short_1.S2P
8 run8_r1c2_pristine Wafer2_r1_c2_pristine_1.S2P
9 run9_r1c2_pristine Wafer2_r1_c2_pristine 2_1.S2P
10 run10_r1c3_pristine Wafer2_r1_c3_pristine_1.S2P
11 run11_r1c4_pristine Wafer2_r1_c4_pristine_1.S2P
12 run12_r1c5_pristine Wafer2_r1_c5_pristine_1.S2P
13 run13_r1c6_pristine Wafer2_r1_c6_pristine_1.S2P
14 run14_r1c7_pristine Wafer2_r1_c7_pristine_1.S2P
15 run15_r1c7_pristine Wafer2_r1_c7_pristine 2_1.S2P
16 run16_r1c8_pristine Wafer2_r1_c8_pristine_1.S2P
17 run17_r1c9_pristine Wafer2_r1_c9_pristine_1.S2P
18 run18_rNonecNone_thru ISS_thru_LRM+_log_1.S2P
19 run19_r1c2_pristine Wafer2_r1_c2_pristine_log_1.S2P
20 run20_r1c3_pristine Wafer2_r1_c3_pristine_log_1.S2P
21 run21_r1c4_pristine Wafer2_r1_c4_pristine_log_1.S2P
22 run22_r1c5_pristine Wafer2_r1_c5_pristine_log_1.S2P
23 run23_r1c6_pristine Wafer2_r1_c6_pristine_log_1.S2P
24 run24_r1c7_pristine Wafer2_r1_c7_pristine_log_1.S2P
25 run25_r1c8_pristine Wafer2_r1_c8_pristine_log_1.S2P
26 run26_r1c9_pristine Wafer2_r1_c9_pristine_log_1.S2P
27 run27_r1c9_smallform Wafer2_r1_c9_smallform_log_1.S2P
28 run28_r1c8_smallform Wafer2_r1_c8_smallform_log_1.S2P
29 run29_r1c7_smallform Wafer2_r1_c7_smallform_log_1.S2P
30 run30_r1c6_smallform Wafer2_r1_c6_smallform_log_1.S2P
31 run31_r1c5_smallform Wafer2_r1_c5_smallform_log_1.S2P
32 run32_r1c4_smallform Wafer2_r1_c4_smallform_log_1.S2P
33 run33_r1c3_smallform Wafer2_r1_c3_smallform_log_1.S2P
34 run34_r1c2_smallform Wafer2_r1_c2_smallform_log_1.S2P
35 run35_r1c9_fullform Wafer2_r1_c9_fullform_log_1.S2P
36 run36_r1c8_fullform Wafer2_r1_c8_fullform_log_1.S2P
37 run37_r1c7_fullform Wafer2_r1_c7_fullform_log_1.S2P
38 run38_r1c7_fullform Wafer2_r1_c7_fullform_log 2_1.S2P
39 run39_r1c6_fullform Wafer2_r1_c6_fullform_log_1.S2P
40 run40_r1c5_fullform Wafer2_r1_c5_fullform_log_1.S2P
41 run41_r1c4_fullform Wafer2_r1_c4_fullform_log_1.S2P
42 run42_r1c3_fullform Wafer2_r1_c3_fullform_log_1.S2P
43 run43_r1c2_fullform Wafer2_r1_c2_fullform_log_1.S2P
1 run1_r2c1_thru Wafer3_r2_c1_thru.S2P
2 run2_r2c2_open Wafer3_r2_c2_open.S2P
3 run3_r2c2_opensig Wafer3_r2_c2_opensignal.S2P
4 run4_r2c3_short Wafer3_r2_c3_short.S2P
5 run5_r2c4_pristine Wafer3_r2_c4_pristine.S2P
6 run6_r2c4_pristine Wafer3_r2_c4_pristine 2.S2P
7 run7_r2c4_pristine Wafer3_r2_c4_pristine 3.S2P
8 run8_r2c4_pristine Wafer3_r2_c4_pristine 4.S2P
9 run9_r2c4_pristine Wafer3_r2_c4_pristine 5.S2P
10 run10_r2c5_pristine Wafer3_r2_c5_pristine.S2P
11 run11_r3c1_thru Wafer3_r3_c1_thru.S2P
12 run12_r3c2_open Wafer3_r3_c2_open.S2P
13 run13_r3c3_opensig Wafer3_r3_c3_opensignal.S2P
14 run14_r3c4_short Wafer3_r3_c4_short.S2P
15 run15_r3c5_pristine Wafer3_r3_c5_pristine.S2P
16 run16_r3c5_pristine Wafer3_r3_c5_pristine 2.S2P
17 run17_r3c6_pristine Wafer3_r3_c6_pristine.S2P
18 run18_r3c6_pristine Wafer3_r3_c6_pristine 2.S2P
19 run19_r3c6_pristine Wafer3_r3_c6_pristine 3.S2P
20 run20_r3c6_pristine Wafer3_r3_c6_pristine_pos0.0dc.S2P
21 run21_r3c6_pristine Wafer3_r3_c6_pristine_pos10dc.S2P
22 run22_r3c6_pristine Wafer3_r3_c6_pristine_pos20dc.S2P
23 run23_r3c6_pristine Wafer3_r3_c6_pristine_pos25dc.S2P
24 run24_r3c6_pristine Wafer3_r3_c6_pristine_pos27dc.S2P
25 run25_r3c6_pristine Wafer3_r3_c6_pristine_pos29dc.S2P
26 run26_r3c6_pristine Wafer3_r3_c6_pristine_pos31dc.S2P
27 run27_r2c5_pristine Wafer3_r2_c5_pristine_pos0.0dc.S2P
28 run28_r2c5_pristine Wafer3_r2_c5_pristine_pos1.0dc.S2P
29 run29_r2c5_pristine Wafer3_r2_c5_pristine_pos10dc.S2P
30 run30_r2c5_pristine Wafer3_r2_c5_pristine_pos15dc.S2P
31 run31_r2c5_pristine Wafer3_r2_c5_pristine_pos20dc.S2P
32 run32_r2c5_pristine Wafer3_r2_c5_pristine_pos25dc.S2P
33 run33_r2c5_pristine Wafer3_r2_c5_pristine_pos30dc.S2P
34 run34_r2c5_pristine Wafer3_r2_c5_pristine_pos35dc.S2P
35 run35_r2c5_pristine Wafer3_r2_c5_pristine_pos40dc.S2P

CPW Memristor 1 - Bias T Experiment¶

Import Data¶

In [ ]:
# Define the path to the directory containing the VNA data
directory_2 = ('/Users/horatiocox/Desktop/VNA_Analysis/CPW_mem_oscillator_220524/Memristor/');
# Import the data from the VNA files
s2p_files_2 = import_data(directory_2);
# Remove duplicate frequency points from all the thru data to prevent errors with skrf functions
s2p_files_2 = duplicate_check(s2p_files_2);
1 run1_r0c0_thru Wafer0_r0_c0_ISS_thru_LRM+.S2P
2 run2_r10c1_thru Wafer2_r10_c1_thru.S2P
3 run3_r10c2_thru Wafer2_r10_c2_thru.S2P
4 run4_r10c3_thru Wafer2_r10_c3_thru.S2P
5 run5_r10c4_thru Wafer2_r10_c4_thru.S2P
6 run6_r10c5_open Wafer2_r10_c5_open.S2P
7 run7_r10c6_open Wafer2_r10_c6_open.S2P
8 run8_r10c7_opennarrow Wafer2_r10_c7_opennarrow.S2P
9 run9_r10c8_openverynarrow Wafer2_r10_c8_openverynarrow.S2P
10 run10_r10c9_opensig Wafer2_r10_c9_opensig.S2P
11 run11_r10c10_opensig Wafer2_r10_c10_opensig.S2P
12 run12_r10c12_short Wafer2_r10_c12_short.S2P
13 run13_r10c13_short Wafer2_r10_c13_short.S2P
14 run14_r10c14_thrunotaper Wafer2_r10_c14_thrunotaper.S2P
15 run15_r10c15_thrunotaper Wafer2_r10_c15_thrunotaper.S2P
16 run16_r10c16_opennotaper Wafer2_r10_c16_opennotaper.S2P
17 run17_r10c17_opennotaper Wafer2_r10_c17_opennotaper.S2P
18 run18_r10c18_opensignotaper Wafer2_r10_c18_opensignotaper.S2P
19 run19_r10c19_opensignotaper Wafer2_r10_c19_opensignotaper.S2P
20 run20_r10c20_shortnotaper Wafer2_r10_c20_shortnotaper.S2P
21 run21_r10c21_shortnotaper Wafer2_r10_c21_shortnotaper.S2P
22 run22_r1c2_formed Wafer2_r1_c2_formedpreviously.S2P
23 run23_r2c1_pristine Wafer2_r2_c1_pristine.S2P
24 run24_r2c1_pristine Wafer2_r2_c1_pristine_pos0.2dc.S2P
25 run25_r2c1_pristine Wafer2_r2_c1_pristine_pos0.4dc.S2P
26 run26_r2c1_pristine Wafer2_r2_c1_pristine_pos0.6dc.S2P
27 run27_r2c1_pristine Wafer2_r2_c1_pristine_pos0.8dc.S2P
28 run28_r2c1_pristine Wafer2_r2_c1_pristine_pos1.0dc.S2P
29 run29_r2c1_pristine Wafer2_r2_c1_pristine_pos1.2dc.S2P
30 run30_r2c1_pristine Wafer2_r2_c1_pristine_pos1.4dc.S2P
31 run31_r2c1_pristine Wafer2_r2_c1_pristine_pos1.6dc.S2P
32 run32_r2c1_pristine Wafer2_r2_c1_pristine_neg0.2dc.S2P
33 run33_r2c1_pristine Wafer2_r2_c1_pristine_neg0.4dc.S2P
34 run34_r2c1_pristine Wafer2_r2_c1_pristine_neg0.6dc.S2P
35 run35_r2c1_pristine Wafer2_r2_c1_pristine_neg0.8dc.S2P
36 run36_r2c1_pristine Wafer2_r2_c1_pristine_neg1.0dc.S2P
37 run37_r2c1_pristine Wafer2_r2_c1_pristine_neg1.2dc.S2P
38 run38_r2c1_pristine Wafer2_r2_c1_pristine_neg1.4dc.S2P
39 run39_r2c1_pristine Wafer2_r2_c1_pristine_neg1.6dc.S2P
40 run40_r2c1_pristine Wafer2_r2_c1_pristine_neg1.8dc.S2P
41 run41_r2c1_pristine Wafer2_r2_c1_pristine_neg2.0dc.S2P
42 run42_r2c1_formed Wafer2_r2_c1_formed_0dc.S2P
43 run43_r2c1_formed Wafer2_r2_c1_formed_pos0.0dc.S2P
44 run44_r2c1_formed Wafer2_r2_c1_formed_pos0.4dc.S2P
45 run45_r2c1_formed Wafer2_r2_c1_formed_pos0.8dc.S2P
46 run46_r2c1_formed Wafer2_r2_c1_formed_pos1.2dc.S2P
47 run47_r2c1_formed Wafer2_r2_c1_formed_pos1.4dc.S2P
48 run48_r2c1_formed Wafer2_r2_c1_formed_neg0.4dc.S2P
49 run49_r2c1_formed Wafer2_r2_c1_formed_neg0.8dc.S2P
50 run50_r2c1_formed Wafer2_r2_c1_formed_neg1.2dc.S2P
51 run51_r2c1_formed Wafer2_r2_c1_formed_neg1.2dc_repeat.S2P
52 run52_r2c1_formed Wafer2_r2_c1_formed_neg1.2dc_repeat2.S2P
53 run53_r2c1_formed Wafer2_r2_c1_formed_neg1.2dc_repeat3.S2P
54 run54_r2c1_formed Wafer2_r2_c1_formed_neg1.2dc_repeat4.S2P
55 run55_r2c1_formed Wafer2_r2_c1_formed_neg0dc_repeat5.S2P
56 run56_r2c1_set Wafer2_r2_c1_reset.S2P
57 run57_r2c1_set Wafer2_r2_c1_set.S2P
58 run58_r2c1_set Wafer2_r2_c1_set2.S2P
59 run59_r2c1_set Wafer2_r2_c1_set3.S2P
60 run60_r2c1_set Wafer2_r2_c1_reset2.S2P
61 run61_r2c1_set Wafer2_r2_c1_set4.S2P
62 run62_r2c1_set Wafer2_r2_c1_set5.S2P
63 run63_r2c1_set Wafer2_r2_c1_set6.S2P
64 run64_r2c1_set Wafer2_r2_c1_reset3.S2P
65 run65_r2c1_set Wafer2_r2_c1_set7.S2P
66 run66_r2c1_set Wafer2_r2_c1_set8.S2P
67 run67_r2c1_set Wafer2_r2_c1_reset4.S2P
68 run68_r2c1_set Wafer2_r2_c1_set9.S2P

Plot Raw S-Params¶

In [ ]:
# Select ISS thru, on wafer thru, on wafer open and compare in one color to a pristine/formed/reset device in another color
raw_data = subgen(s2p_files_2, run_nums =[[1,2,6,], [23,42,56] ] )
# Plot the data
f = plt.figure(figsize=(20,10),dpi=200)
gs = f.add_gridspec(2, 2)

ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])
ax2 = f.add_subplot(gs[1, 0])
ax3 = f.add_subplot(gs[1, 1])

sub_plot(ax=ax, dev_subset=raw_data, plot_type=['s_db'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [-55,0],x_range='0.01-20ghz')
sub_plot(ax=ax1, dev_subset=raw_data, plot_type=['s_deg'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range=[-50,100], x_range='0.01-20ghz')
sub_plot(ax=ax2, dev_subset=raw_data, plot_type=['s_db'], log_x=False, m_port=[1], n_port=[1], deembed_data=False, 
         y_range = [-55,0],x_range='0.01-20ghz')
sub_plot(ax=ax3, dev_subset=raw_data, plot_type=['s_deg'], log_x=False, m_port=[1], n_port=[1], deembed_data=False, 
         y_range=[-100,0], x_range='0.01-20ghz')

plt.show()
No description has been provided for this image

Now Focusing in on the S21¶

In [ ]:
f = plt.figure(figsize=(20,5),dpi=200)
gs = f.add_gridspec(1, 2)

ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])

sub_plot(dev_subset=raw_data, plot_type=['s_db'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [-2,0],x_range='0.01-20ghz', ax=ax)
sub_plot(dev_subset=raw_data, plot_type=['s_deg'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range=[-50,100], x_range='0.01-20ghz', ax=ax1)

plt.show()
No description has been provided for this image

Initial Analysis¶

  • The ISS shows almost no loss for S21 as expected
  • The on wafer CPW thru has quite a low loss
  • The On wafer Thru/Memristor have an oscillation "noise" which is very significant and likely due to an impedance mismatch
    • This noise is greater than the difference between pristine/formed/reset states
    • It will need to be removed before any clear difference between memristor states can be determined

Open Short De-embedding¶

In [ ]:
#-------------------Grouping-------------------
# Select the On Wafer Calibration files to be used
ISS_thru = [s for s in s2p_files_2 if s.state == 'thru' and s.wafer_number == 0]
cal_thru = [s for s in s2p_files_2 if s.state == 'thru' and s.wafer_number != 0]
cal_open = [s for s in s2p_files_2 if s.state == 'open' or s.state == 'opensig']
cal_short = [s for s in s2p_files_2 if s.state == 'short']

#-------------------De-Embedding-------------------
print('open_short_thru',len(cal_open),len(cal_short),len(cal_thru))
 #whether to plot the de-embedding results
OS = calibration_OS(cal_open, cal_short, cal_thru, plot_cal = False) #calibration object outputted from all the on wafer measurements
TX = calibration_2x(cal_thru, plot_cal = False) #calibration object outputted from all the on wafer measurements

# Plot the data with the deembeding applied and compare to the raw data
f = plt.figure(figsize=(20,8),dpi=200)
gs = f.add_gridspec(1, 2)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])

# deembeding is applied with an argument in the function and the deembeding object desired is passed to the function
sub_plot(ax=ax, dev_subset=raw_data, plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [0.8,1.05],x_range='0.01-20ghz', cal_in = [])
sub_plot(ax=ax1, dev_subset=raw_data, plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=True, 
         y_range=[0.8,1.05], x_range='0.01-20ghz',cal_in = OS)

plt.show()
open_short_thru 4 2 4
[29493.25017913594, 29493.828865204905, 29493.097293820058, 29492.936062208333, 29489.754914854297, 29493.548249662417, 29489.8297148353, 29490.92647900279]
Best de-embedding protocol: dm[4] = 29489.754914854297, worst:dm[1] = 29493.828865204905
[22093.334805985014, 22166.101440143848, 22111.505466789735, 22149.911859675216]
Best de-embedding protocol: dm[0] = 22093.334805985014, worst:dm[1] = 22166.101440143848
No description has been provided for this image

Notes¶

  • The de-embedding improves the thru device measurably
  • Definitely shifts the memristor so more signal going through for s21
  • Though the on wafer thru now averages around s21 = 1 - the noise remains just as large!
  • The noise continues to prevent any effective comparison between the memristors

2x Thru De-embedding¶

In [ ]:
#-------------------De-Embedding-------------------
TX = calibration_2x(cal_thru, plot_cal = False) #calibration object outputted from all the on wafer measurements

# Plot the data with the deembeding applied and compare to the raw data
f = plt.figure(figsize=(20,8),dpi=200)
gs = f.add_gridspec(1, 2)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])

# deembeding is applied with an argument in the function and the deembeding object desired is passed to the function
sub_plot(ax=ax, dev_subset=raw_data, plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [0.8,1.05],x_range='0.01-20ghz', cal_in = [])
sub_plot(ax=ax1, dev_subset=raw_data, plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=True, 
         y_range=[0.8,1.05], x_range='0.01-20ghz',cal_in = TX)

plt.show()
[22093.334805985014, 22166.101440143848, 22111.505466789735, 22149.911859675216]
Best de-embedding protocol: dm[0] = 22093.334805985014, worst:dm[1] = 22166.101440143848
No description has been provided for this image

Notes¶

  • Again de-embedding improves the thru device measurably
  • Again Definitely shifts the memristor so more signal going through for s21
  • Again Though the on wafer thru now averages around s21 = 1 - the noise remains just as large!
  • Difference is that the 2x appears to be better - though it uses the thru so comparison on a thru device probaly not representative

FFT filtering to remove oscillations¶

In [ ]:
# Demo for the on-wafer thru device
thru_filt_test = [copy.deepcopy(cal_thru[0])]
# Select bandstop frequency components
threshold_values = [[1.8e-8,2.2e-8],[5.9e-8,6.15e-8],[3.9e-8,4.05e-8],[2.9e-8,3.05e-8],[7.95e-8,8.05e-8],[6.45e-8,6.55e-8],[6.96e-8,7.06e-8]]
# Apply the FFT, filter out components then IFFT
s2p_test_filt = fourier_filter(thru_filt_test, threshold = threshold_values,t_window = 0.02)
No description has been provided for this image

Notes¶

  • t_window applies a tukey window to the data before applying the FFT - this prevents spectral leakage
  • This sacrifices some of the higher and lower frequencies but massively improves the quality of the filtered data
  • a higher t_window value applies a sharper window - so I have kept it as small as possible
In [ ]:
# Plot the data with and without FFT filtering
f = plt.figure(figsize=(20,8),dpi=200)
gs = f.add_gridspec(1, 2)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])

sub_plot(ax=ax, dev_subset=[[cal_thru[0]]], plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [0.95,1.0],x_range='0.01-20ghz')
sub_plot(ax=ax1, dev_subset= [s2p_test_filt], plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range=[0.95,1.0], x_range='0.01-20ghz')

plt.show()
No description has been provided for this image

De-embedding on FFT filtered data¶

In [ ]:
#### Need to re-do the calibration on fully FFT filtered data before applying it!

s2p_files_2_filt = copy.deepcopy(s2p_files_2)
# Select bandstop frequency components
threshold_values = [[1.8e-8,2.2e-8],[5.9e-8,6.15e-8],[3.9e-8,4.05e-8],[2.9e-8,3.05e-8],[7.95e-8,8.05e-8],[6.45e-8,6.55e-8],[6.96e-8,7.06e-8]]
# Apply the FFT, filter out components then IFFT
s2p_files_2_filt = fourier_filter(s2p_files_2_filt, threshold = threshold_values,t_window = 0.02) #apply to deepcopy to avoid modifying the original data


#-------------------Grouping-------------------
# Select the On Wafer Calibration files to be used
ISS_thru_filt = [s for s in s2p_files_2_filt if s.state == 'thru' and s.wafer_number == 0]
cal_thru_filt = [s for s in s2p_files_2_filt if s.state == 'thru' and s.wafer_number != 0]
cal_open_filt = [s for s in s2p_files_2_filt if s.state == 'open' or s.state == 'opensig']
cal_short_filt = [s for s in s2p_files_2_filt if s.state == 'short']

#-------------------De-Embedding-------------------
OS_filt = calibration_OS(cal_open_filt, cal_short_filt, cal_thru_filt, plot_cal = False) #calibration object outputted from all the on wafer measurements
TX_filt = calibration_2x(cal_thru_filt, plot_cal = False) #calibration object outputted from all the on wafer measurements
[28353.392561250494, 28370.406436998805, 28354.071596680602, 28371.07807926913, 28353.673722217638, 28370.669529166313, 28354.12137072636, 28371.112750655735]
Best de-embedding protocol: dm[0] = 28353.392561250494, worst:dm[7] = 28371.112750655735
[21952.43768002349, 21978.870347280088, 21979.473121506657, 21990.126025888083]
Best de-embedding protocol: dm[0] = 21952.43768002349, worst:dm[3] = 21990.126025888083
No description has been provided for this image
In [ ]:
# Plot the data with and without FFT filtering
f = plt.figure(figsize=(20,12),dpi=200)
gs = f.add_gridspec(3, 1)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[1, 0])
ax2 = f.add_subplot(gs[2, 0])

#FFT only
sub_plot(ax=ax, dev_subset=[s2p_test_filt], plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1],  deembed_data=False, 
         y_range = [0.95,1.02],x_range='0.01-20ghz')
# FFT and OS deembeding
sub_plot(ax=ax1, dev_subset=[s2p_test_filt], plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1],  deembed_data=True, 
         y_range = [0.95,1.02],x_range='0.01-20ghz',cal_in = OS_filt)
# FFT and 2X deembeding
sub_plot(ax=ax2, dev_subset= [s2p_test_filt], plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=True, 
         y_range=[0.95,1.02], x_range='0.01-20ghz',cal_in = TX_filt)

plt.show()
No description has been provided for this image

FFT filtering on De-embedded data¶

In [ ]:
# Go through and de-embed all data
sp2_files_2_OS = copy.deepcopy(s2p_files_2)
sp2_files_2_TX = copy.deepcopy(s2p_files_2)

for f in sp2_files_2_OS:
    f.network = OS.deembed(f.network)
for f in sp2_files_2_TX:
    f.network = TX.deembed(f.network)

# Extract the on wafer thru 
thru_filt_OS = [copy.deepcopy(sp2_files_2_OS[1])]
# Select bandstop frequency components
threshold_values = [[1.8e-8,2.2e-8],[5.9e-8,6.15e-8],[3.9e-8,4.05e-8],[2.9e-8,3.05e-8],[7.95e-8,8.05e-8],[6.45e-8,6.55e-8],[6.96e-8,7.06e-8]]
# Apply the FFT, filter out components then IFFT
s2p_2_OS_filt = fourier_filter(thru_filt_OS, threshold = threshold_values,t_window = 0.02)

# Extract the on wafer thru 
thru_filt_TX = [copy.deepcopy(sp2_files_2_TX[1])]
# Select bandstop frequency components
threshold_values = [[1.8e-8,2.2e-8],[5.9e-8,6.15e-8],[3.9e-8,4.05e-8],[2.9e-8,3.05e-8],[7.95e-8,8.05e-8],[6.45e-8,6.55e-8],[6.96e-8,7.06e-8]]
# Apply the FFT, filter out components then IFFT
s2p_2_TX_filt = fourier_filter(thru_filt_TX, threshold = threshold_values,t_window = 0.02)  
No description has been provided for this image
No description has been provided for this image
In [ ]:
# Plot the data with and without FFT filtering
f = plt.figure(figsize=(20,8),dpi=200)
gs = f.add_gridspec(1, 2)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])

sub_plot(ax=ax, dev_subset=[s2p_2_OS_filt], plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [0.95,1.05],x_range='0.01-20ghz')
sub_plot(ax=ax1, dev_subset= [s2p_2_TX_filt], plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range=[0.95,1.05], x_range='0.01-20ghz')

plt.show()
No description has been provided for this image

Notes¶

  • It is much noisier if you do the FFT on the de-embedded data
  • seems to be better to FFT the data, filter then apply the de-embedding
  • Though the 2x de-embedding appears perfect, this is deembeding the thru device directly from itself
    • as the same device is used for the de-embedding and reference
    • unfortunately the quality is not the same when applied to memristors

Best so Far on Memristor¶

FFT all the data, then do the calibration on the FFT filtered data, then do the de-embedding 2x

In [ ]:
# Select the data from the already FFT filtered fulll data set
filtered_memristor = subgen(s2p_files_2_filt, run_nums =[[1,2,6,], [23,42,56] ] )
raw_data = subgen(s2p_files_2, run_nums =[[1,2,6,], [23,42,56] ] )

# Plot the FFT data with and without de embedding
f = plt.figure(figsize=(60,30),dpi=200)
gs = f.add_gridspec(3, 5)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])

sub_plot(ax=ax, dev_subset = raw_data, plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [0.7,1.0],x_range='0.01-20ghz')
# Apply the filtered TX deembeding to the filtered data
sub_plot(ax=ax1, dev_subset = filtered_memristor, plot_type=['s_mag'], log_x=False, m_port=[2], n_port=[1], deembed_data=True, 
         y_range=[0.7,1.0], x_range='0.01-20ghz',cal_in = TX_filt)

plt.show()
No description has been provided for this image

Notes¶

  • Overall a large improvement in both reducing the noise and increasing the S21 transmission
  • Now we can compare memristor states

Memristor state comparison¶

In [ ]:
# Select the data from the already FFT filtered fulll data set
run_n =[[1,2,3,4,5,6], [56,60,64,67], [57,58,59,61,62,63,65,66,68] ]
filtered_memristor = subgen(s2p_files_2_filt, run_nums = run_n )
raw_data = subgen(s2p_files_2, run_nums = run_n )

# Plot the FFT data with and without de embedding
f = plt.figure(figsize=(20,8),dpi=200)
gs = f.add_gridspec(1, 2)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])

sub_plot(ax=ax, dev_subset = raw_data, plot_type=['s_mag'], log_x=True, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = None,x_range='0.1-20ghz')
# Apply the filtered TX deembeding to the filtered data
sub_plot(ax=ax1, dev_subset = filtered_memristor, plot_type=['s_mag'], log_x=True, m_port=[2], n_port=[1], deembed_data=True, 
         y_range=None, x_range='0.1-20ghz',cal_in = OS_filt)

plt.show()
No description has been provided for this image

Notes¶

  • Set is where we see the largest variation due to big differences in the resistance of the LRS
    • potentially filamental vs interface based switching
  • RESET into the HRS yields a much tighter range of values
    • Is still a clear variation in the HRS
  • A significant finding here is not only that the resistance switching is visible at the lower frequencies but that at higher frequencies there are clear differences in the S-params which I believe indicates differences in the permittivity/capacitance of devices
  • Clearly these devices can be used to modulate microwave signals across a broad range of frequencies which is a good start

Look At Power inputz and other params¶

In [ ]:
# Select the data from the already FFT filtered fulll data set
run_n =[[1,2,3,4,5,6], [56,60,64,67], [57,58,59,61,62,63,65,66,68] ]
filtered_memristor = subgen(s2p_files_2_filt, run_nums = run_n )
raw_data = subgen(s2p_files_2, run_nums = run_n )

# Plot the FFT data with and without de embedding
f = plt.figure(figsize=(20,8),dpi=200)
gs = f.add_gridspec(1, 2)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])

#Plotting and comparing only the filtered data now
sub_plot(ax=ax, dev_subset = filtered_memristor, plot_type=['inputz'], log_x=True, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [0,200],x_range='0.1-20ghz',cal_in = OS_filt)
# Apply the filtered TX deembeding to the filtered data
sub_plot(ax=ax1, dev_subset = filtered_memristor, plot_type=['power'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range=[0.8,0.95], x_range='0.1-20ghz',cal_in = OS_filt)

plt.show()
No description has been provided for this image

Normalize the input impedance and s parameters to a pristine reference measurement¶

In [ ]:
# Select the data from the already FFT filtered fulll data set
run_n =[ [23,56,60,64,67], [23,57,58,59,61,62,63,65,66,68] ]
filtered_memristor = subgen(s2p_files_2_filt, run_nums = run_n )
raw_data = subgen(s2p_files_2, run_nums = run_n )

# Plot the FFT data with and without de embedding
f = plt.figure(figsize=(20,8),dpi=200)
gs = f.add_gridspec(1, 2)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[0, 1])

#Plotting and comparing only the filtered data now
sub_plot(ax=ax, dev_subset = filtered_memristor, plot_type=['znorm'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [0.9,1.1],x_range='0.1-20ghz',cal_in = OS_filt)
# Apply the filtered TX deembeding to the filtered data
sub_plot(ax=ax1, dev_subset = filtered_memristor, plot_type=['snorm'], log_x=False, m_port=[1], n_port=[2], deembed_data=False, 
         y_range=[0.98,1.005], x_range='0.1-20ghz',cal_in = OS_filt)

plt.show()
No description has been provided for this image

Now let us compare the pristine DC bias measurements in the s-norm mode¶

In [ ]:
# Select the data from the already FFT filtered fulll data set
run_n =[ [23,56,60,64,67], [31,27,23,35,39,41],[23,57,58,59,61,62,63,65,66,68] ]
run_n2 = [ [1], [31,27,23,35,39,41]]
run_n3 = [ [23,56,60,64,67], [31,27,23,35,39,41],[27,57,58,59,61,62,63,65,66,68] ]
filtered_memristor = subgen(s2p_files_2_filt, run_nums = run_n )
filtered_memristor2 = subgen(s2p_files_2_filt, run_nums = run_n2 )
filtered_memristor3 = subgen(s2p_files_2_filt, run_nums = run_n3 )

# Plot the FFT data with and without de embedding
f = plt.figure(figsize=(15,10),dpi=200)
gs = f.add_gridspec(3, 1)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[1, 0])
ax2 = f.add_subplot(gs[2, 0])

# Comparing the DC biases
sub_plot(ax=ax, dev_subset = filtered_memristor2, plot_type=['snorm'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [0.997,1.002],x_range='0.1-20ghz',cal_in = OS_filt)
# Comparing DC biases with switched states
sub_plot(ax=ax1, dev_subset = filtered_memristor, plot_type=['snorm'], log_x=False, m_port=[1], n_port=[2], deembed_data=False, 
         y_range=[0.98,1.005], x_range='0.1-20ghz',cal_in = OS_filt)
# DC biases, switched states but using a different 'pristine' object to normalise
sub_plot(ax=ax2, dev_subset = filtered_memristor3, plot_type=['snorm'], log_x=False, m_port=[1], n_port=[2], deembed_data=False, 
         y_range=[0.98,1.005], x_range='0.1-20ghz',cal_in = OS_filt)

plt.show()
No description has been provided for this image

Notes¶

  • In plot 1 we can see that the DC biasing gives a slight shift in the s-params
    • Though this is incredibly slight and at the limit of the noise
  • In plot 2 the DC bias are shown in blue-green with the HRS in greys and the LRS in yellow-orange
  • Plot 3 is the same as plot 2 but the normalisation device is changed from pristine, to pristine_DC=0.2V
    • The reason for this is that I wanted to see if the small peaks are a product of normalisation or a consistent difference between pristine/formed devices
    • It appears that there are small localised frequency variations between pristine/formed
    • These may be real features of interest if consistent across other devices and not a product of data processing

Comparing SET(LRS)/RESET(HRS)¶

In [ ]:
# Select the data from the already FFT filtered fulll data set
run_n =[ [23,56,60,64,67],[23,57,58,59,61,62,63,65,66,68] ]
#pairs of set/reset to compare
run_n2 = [ [23,56],[56,57],[60,58],[64,59],[67,61] ]

filtered_memristor = subgen(s2p_files_2_filt, run_nums = run_n )
filtered_memristor2 = subgen(s2p_files_2_filt, run_nums = run_n2 )

# Plot the FFT data with and without de embedding
f = plt.figure(figsize=(15,10),dpi=200)
gs = f.add_gridspec(2, 1)
ax = f.add_subplot(gs[0, 0])
ax1 = f.add_subplot(gs[1, 0])


# Comparing all SET/RESET devices
sub_plot(ax=ax, dev_subset = filtered_memristor, plot_type=['snorm'], log_x=False, m_port=[2], n_port=[1], deembed_data=False, 
         y_range = [0.98,1.005],x_range='0.1-20ghz',cal_in = OS_filt)
# Comparing SET/RESET device pairs
sub_plot(ax=ax1, dev_subset = filtered_memristor2, plot_type=['snorm'], log_x=False, m_port=[1], n_port=[2], deembed_data=False, 
         y_range=[0.995,1.002], x_range='0.1-20ghz',cal_in = OS_filt)


plt.show()
No description has been provided for this image

Notes¶

  • Generally the SET(LRS have lower s21 reflecting lower r? but also changes in c?)
  • the first pair of data in grey are pristine vs reset and the spike at 10GHz and a few other places are visible
  • These spikes arent visible from SET to RESET implying that if these spikes are created in the forming they are not altered in the SET/RESET process

Rest of Data¶

In [ ]:
# # Step 0 - check fourier filter on a thru calibration and a device to compare the frequency spikes

# threshold_values = [[1.8e-8,2.2e-8],[5.9e-8,6.15e-8],[3.9e-8,4.05e-8],[2.9e-8,3.05e-8],[7.95e-8,8.05e-8],[6.45e-8,6.55e-8],[6.96e-8,7.06e-8]]
# ISS_filt_test = [copy.deepcopy(s2p_files[0])]
# s2p_filt = fourier_filter(ISS_filt_test, threshold = threshold_values) 

# thru_filt_test = [copy.deepcopy(s2p_files[1])]
# s2p_filt = fourier_filter(thru_filt_test, threshold = threshold_values)

# pristine_filt_test = [copy.deepcopy(s2p_files[24])]
# s2p_filt = fourier_filter(pristine_filt_test, threshold = threshold_values)




# ## Step 1 - fourier filter the initial files to remove noise
# s2p_filt = copy.deepcopy(s2p_files)
# s2p_filt = fourier_filter(s2p_filt, threshold = threshold_values) #apply to deepcopy to avoid modifying the original data

# # Step 2 - check a fourier deconvolution of all the thru data 
# cal_thru = [s for s in s2p_filt if s.state == 'thru' and s.wafer_number != 0]
# s2p_filt_convolve = copy.deepcopy(s2p_files)
# s2p_filt_convolve = fourier_convolve(s2p_filt_convolve, cal_thru) #apply to deepcopy to avoid modifying the original data

# # Step 3 - what about a time domain deconvolution??
# cal_thru = [s for s in s2p_filt if s.state == 'thru' and s.wafer_number != 0]
# s2p_filt_inverse = copy.deepcopy(s2p_files)
# s2p_filt_inverse = fourier_inverse(s2p_filt_inverse, cal_thru) #apply to deepcopy to avoid modifying the original data




# # Group files by their state so I can plot and compare states
# pristine = [s for s in s2p_filt if s.state == 'pristine']
# formed = [s for s in s2p_filt if s.state in ['formed', 'smallform', 'fullform']]

# # Group files with the same [r_number, c_number] values together so I can plot each device in all its states on one graph
# # Stores a list of S2PFile objects for each device in a dictionary, "dev", with the key being the device's [r_number, c_number] values
# #thus dev['11'] will have all the data for the device in row 1 column 1
# dev = {}
# for s in s2p_files:
#     key = f"r{s.dev_row}c{s.dev_col}"
#     if key in dev:
#         dev[key].append(s)
#     else:
#         dev[key] = [s]





# #-------------------Subsetting-------------------
# #dev_subs = subgen(s2p_files, run_nums =[[1,2,3,4,5,6], [31,27,23,35,39,41], [47,42,50]   ] )
# #dev_subs_filt = subgen(s2p_filt, run_nums =[[1,2,3,4,5,6], [31,27,23,35,39,41], [47,42,50]   ] )
# #dev_subs = subgen(s2p_files, run_nums =[[1,2], [23], [42]   ] )

# dev_subs = subgen(s2p_files, run_nums =[[1,2,3,4,5,6], [56,60,64,67], [57,58,59,61,62,63,65,66,68]   ] )
# dev_subs_filt = subgen(s2p_filt, run_nums =[[1,2,3,4,5,6], [56,60,64,67], [57,58,59,61,62,63,65,66,68]   ] )
# dev_subs_convolve = subgen(s2p_filt_convolve, run_nums =[[1,2,3,4,5,6], [56,60,64,67], [57,58,59,61,62,63,65,66,68]   ] )
# dev_subs_inverse = subgen(s2p_filt_inverse, run_nums =[[1,2,3,4,5,6], [56,60,64,67], [57,58,59,61,62,63,65,66,68]   ] )
# #-------------------Plotting-------------------
# #def keyplot(OS, dev, dev_selection = None, sub_set = [], y_range = None,
#            # x_range = slice(0,-1), log_x = False, plot_type = 'S_db',m_port=[2], n_port=[1]):        
# #'inputz' - plots the input impedance of the device

# x_range_input = "0.02-20ghz"#slice(0,-1)#"0.02-0.8ghz" #
# y_range_input = None#[0,200]#None#[0,200]
# # def subplot(dev_subs = [], cal_in = [], y_range = None,
# #             x_range = slice(0,-1), log_x = False, plot_type = 'S_db',m_port=[2], n_port=[1], deembed_data = True):

# # def subgen(s2p_files, run_nums = [[],[],[]]):




# # fig1 = subplot(dev_subs = dev_subs, cal_in = OS, plot_type = ['power', 'inputz', 'S_db'],
# #                         log_x=False, m_port=[2], n_port=[1],deembed_data = True, y_range=y_range_input, x_range=x_range_input)
# # fig2 = subplot(dev_subs = dev_subs, cal_in = OS, plot_type = ['power', 'inputz', 'S_db'],
# #                         log_x=False, m_port=[2], n_port=[1],deembed_data = False, y_range=y_range_input)


# # fig3 = subplot(dev_subs = dev_subs_filt, cal_in = TX, plot_type = ['s_mag','s_deg'],
# #                         log_x=False, m_port=[2], n_port=[1],deembed_data = True, y_range=y_range_input, x_range=x_range_input)
# # fig3 = subplot(dev_subs = dev_subs_filt, cal_in = OS, plot_type = ['s_mag','s_deg'],
# #                         log_x=False, m_port=[2], n_port=[1],deembed_data = True, y_range=y_range_input, x_range=x_range_input)
# fig4 = subplot(dev_subset = dev_subs, cal_in = OS, plot_type = ['s_mag'],
#                         log_x=False, m_port=[2], n_port=[1],deembed_data = False, y_range=y_range_input, x_range=x_range_input)
# fig4 = subplot(dev_subset = dev_subs_filt, cal_in = OS, plot_type = ['s_mag'],
#                         log_x=False, m_port=[2], n_port=[1],deembed_data = False, y_range=y_range_input, x_range=x_range_input)

# fig4 = subplot(dev_subset = dev_subs_convolve, cal_in = OS, plot_type = ['s_mag'],
#                         log_x=False, m_port=[2], n_port=[1],deembed_data = False, y_range=y_range_input, x_range=x_range_input)

# fig5 = subplot(dev_subset = dev_subs_inverse, cal_in = OS, plot_type = ['s_mag'],
#                         log_x=False, m_port=[2], n_port=[1],deembed_data = False, y_range=y_range_input, x_range=x_range_input)

# plt.show()
In [ ]:
#-------------------Network Set-------------------
#takes a dictionary or list of networks as its input and converts to a network set object that can give errors etc for repeated measurements
# Convert the dev dictionary of lists of s2p files into a dictionary of lists of networks

#need filtering, probably taken from the keyplot function to select the devices and states to include in the network set
# probably actually just want to make this another keyplot function that takes the network set as an input and then plots the data

# dev_networks = {}
# for key, value in dev.items():
#     dev_networks[key] = [s.network for s in value]

# ro_ns = NetworkSet(dev_networks, name='ro set')